package com.fagp.register.handler;

import com.fagp.mew.common.rest.bo.MewSession;
import com.fagp.register.provide.AucFeignService;
import com.zebra.register.BalanceTmsInfo;
import com.zebra.register.LoadBalanceService;
import com.zebra.register.RegisterClientHandler;
import com.zebra.remoting.config.*;
import com.zebra.remoting.protocol.ProcessorType;
import com.zebra.remoting.protocol.ZebraCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
 * TODO 要验证 是否达到人数上限
 */
@Service
@Slf4j
public class RegisterHandler extends RegisterClientHandler {

    @Autowired
    private LoadBalanceService loadBalanceService;
    @Autowired
    private AucFeignService aucFeignService;

    @Override
    public void doHandler(ZebraCommand command) throws Exception {
        if (BasisCommandCode.ASKTMS.cmd() == command.getCmd()){
            AskTmsRequestMessage requestMessage = (AskTmsRequestMessage) command.getRequest();

            long userId = command.getUserId();
            long token = command.getToken();
            MewSession session = aucFeignService.getSession(userId);
            log.info("ASKTMS request info: uid {} ttk {} gameId {} {}", userId, token, command.getGameId(), requestMessage.toString());
            if (null == session || session.tk != token){
                log.error("ASKTMS SERVER: loginUn uid:{} tk:{}", userId, token);
                command.sendFailureCode(StateCode.LoginUn.code());
                return;
            }

            //--------loadBalanceService--------
            ProcessorType processorType = ProcessorType.valueOf(requestMessage.getProcessorType());
            if (null == processorType){
                log.error("ASKTMS SERVER: not SERVER  uid:{} tk:{} processType {}", userId, token, processorType);
                command.sendFailureCode(StateCode.GatewayDowntime.code());
                return;
            }
            BalanceTmsInfo tmsServerInfo;
            int gameId = command.getGameId();
            int cmd = requestMessage.getCmd();
            switch (processorType){
                case L_LOGIN: { tmsServerInfo = getTmsServer(session, cmd, 0); break;}
                case L_RECON: { tmsServerInfo = getTmsServer(session, cmd, 0); break;}
                case G_LOGIN: { tmsServerInfo = getTmsServer(session, cmd, gameId); break;}
                case G_RECON: {
                    if (gameId != session.loc || session.gsid < 1){
                        log.error("ASKTMS SERVER G_RECON: loginUn uid:{} gameId:{} sessionLoc:{} sessionGsid:{} ", userId, gameId, session.loc, session.gsid);
                        command.sendFailureCode(StateCode.LoginUn.code());
                        return;
                    }
                    tmsServerInfo = Optional.ofNullable(loadBalanceService.getTmsBySid(session.gsid)).map( s -> new BalanceTmsInfo(s.getServerId())).orElse(new BalanceTmsInfo(0, gameId == 0 ? StateCode.LobbyServerDowntime.code() : StateCode.GameServerDowntime.code()));
                    break;
                }
                case GM: { tmsServerInfo = getTmsServer(session, cmd, gameId);  break;}
                default:   tmsServerInfo = getTmsServer(session, cmd, gameId);
            }

            doAskTms(command, tmsServerInfo, gameId);
            log.info("---ASKTMS SERVER: uid:{} tk:{} processType {} -> serverId {}", userId, token, processorType, Optional.ofNullable(tmsServerInfo).orElse(new BalanceTmsInfo()).getServerId());
        }
    }

    @Override
    public void doTmsOffline(int tmsid, int serverType) {
        log.info("Offline schedule tmsid {} serType {}", tmsid, serverType);
        aucFeignService.tmsoff(tmsid, serverType);
    }

    private BalanceTmsInfo getTmsServer(MewSession session, int cmd, int gameId){
        return gameId < 1 ? getLobbyTmsServer(session, cmd) : getGameTmsServer(session, cmd, gameId);
    }

    private BalanceTmsInfo getLobbyTmsServer(MewSession session, int cmd){
        TmsServerInfo serverInfo =  session.lsid > 0 ? loadBalanceService.getTmsBySid(session.lsid) : null;
        return serverInfo == null ? loadBalanceService.loadTms(cmd, 0) : new BalanceTmsInfo(serverInfo.getServerId());
    }

    private BalanceTmsInfo getGameTmsServer(MewSession session, int cmd, int gameId){
        TmsServerInfo serverInfo = session.gsid > 0 && session.gid == gameId ? loadBalanceService.getTmsBySid(session.gsid) : null;  //loadBalanceService.loadTms(cmd, gameId);
        return serverInfo == null ? loadBalanceService.loadTms(cmd, gameId) : new BalanceTmsInfo(serverInfo.getServerId());
    }

    private void doAskTms(ZebraCommand command, BalanceTmsInfo tmsServerInfo, int gameId){
        tmsServerInfo = null == tmsServerInfo ? new BalanceTmsInfo(0, gameId == 0 ? StateCode.LobbyServerDowntime.code() : StateCode.GameServerDowntime.code()) : tmsServerInfo;
        if (tmsServerInfo.getServerId() ==0){
            log.error("ASKTMS SERVER: tms is null; {} tms {} ", command.toString(), tmsServerInfo);
            command.sendFailureCode(tmsServerInfo.getStateCode());
            return;
        }
        AskTmsResponseMessage responseMessage = new AskTmsResponseMessage();
        responseMessage.setServerId(tmsServerInfo.getServerId());
        command.sendMessage(responseMessage);

    }

}
